package com_.dxy_test_.zookeeper_.common_config_;

import com.alibaba.fastjson.JSON;
import com_.dxy_test_.zookeeper_.ZkConfig;
import lombok.Data;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

import java.io.IOException;

/**
 * 参考基于Zookeeper实现统一配置管理
 * https://www.cnblogs.com/wrxiang/p/15145405.html
 */
@Data
public class ZkGetConfigClient {

    private Config config;

    /**
     * 初始化获取配置，并给节点绑定监听逻辑
     *
     * @return
     */
    public Config initConfig() {
        ZkClient zk = ZkConfig.zkClient;
        if (!zk.exists(ZkConfig.CONFIG_PATH)) {
//           throw new RuntimeException("配置信息节点不存在");
            return null;
        }
        String content = (String) zk.readData(ZkConfig.CONFIG_PATH);
        config = JSON.parseObject(content, Config.class);
        System.out.println("加载到配置：" + config.toString());

        //监听配置文件修改
        zk.subscribeDataChanges(ZkConfig.CONFIG_PATH, new IZkDataListener() {
            @Override
            public void handleDataChange(String arg0, Object arg1) throws Exception {
                String s = (String) arg1;
                config = JSON.parseObject(s, Config.class);
                System.out.println("**监听到配置文件被修改：" + config.toString());
                //TODO 此处监听到配置变化了，处理统计配置类的修改外
                //还可以对@Value注解的字段进行修改，具体参考：
                //Zookeeper 实现分布式配置管理实现 @Value 的动态变化 (二)：
                //https://blog.csdn.net/houxian1103/article/details/108561661
            }

            @Override
            public void handleDataDeleted(String arg0) throws Exception {
                config = null;
                System.out.println("**监听到配置文件被删除！！！");
            }

        });
        return config;
    }

    /**
     * 订阅配置的应用
     * <p>
     * 先启动ZkConfigTest后，在启动ZkGetConfigClient
     * <p>
     * IDEA模拟启动多个实例的方法
     * https://blog.csdn.net/qq_44761854/article/details/122489698
     *
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        ZkGetConfigClient zkGetConfigClient = new ZkGetConfigClient();
        zkGetConfigClient.initConfig();
        System.in.read();//键盘上输入任何字符就会退出main线程
    }

}
